using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Globalization;

namespace WinCANTool
{
    public partial class ParseSymbols
    {
        public event EventHandler NewSymbols;
        public bool SymbolsInData = false;
        public string CurrentFileName = "None Loaded";

        private FileStream fs;
        private StreamReader newfile;
        private bool FileOpen = false;
        private String ParseIn;
        public enum PState
        {
            START_STATE, MESSAGE_STATE, SUBMESSAGE_STATE,
            DATAWORD_STATE, BITDATA_STATE, ENUM_STATE, MESSAGE_END_STATE,
            SUBMESSAGE_END_STATE, DATAWORD_END_STATE, BITDATA_END_STATE,
            ENUM_END_STATE,MESSAGE_DATA_STATE, MESSAGE_DATA_END
        };
        public PState ParseState;
        public String[] SymbolLine;
        public Message NewMessage;
        public SubMessage NewSubMessage;
        public DataWord NewDataWord;
        public BitData NewBitData;
        public EnumIndex NewEnumData;
        public Symbols MySymbols = new Symbols();
        public bool SymbolsLoaded = false;
        public ArrayList ListIn;

        
        public ArrayList OpenCapturedData(string FileNameIn)
        {
            CurrentFileName = FileNameIn;
            ParseFile_Click(FileNameIn);
            return ListIn;
        }

        public void ClearSymbols()
        {
            MySymbols.NewBit.Clear();
            MySymbols.NewData.Clear();
            MySymbols.NewEnum.Clear();
            MySymbols.NewSubId.Clear();
            MySymbols.NewSymbol.Clear();

        }


        public virtual void SymbolsReady(object sender, EventArgs e)
        {

            if (NewSymbols != null)
                NewSymbols(this, e);
        }



        public void ParseFile_Click(string FileNameIn)
        {
            char[] HexDelimits = { ' ', ',', '.', '=', 'x' };
            char[] TextDelimits = { ' ', ',', '.', '=' };

            if (!FileOpen)
            {
                try
                {

                    fs = new FileStream(FileNameIn,
                                   FileMode.Open);
                    newfile = new StreamReader(fs);
                    FileOpen = true;
                }
                catch
                {
                    MessageBox.Show("File cannot be opened");
                    return;
                }
            }

            fs.Seek(0, SeekOrigin.Begin);
            newfile.DiscardBufferedData();
            ParseState = PState.START_STATE;
            CurrentFileName = FileNameIn;
            ClearSymbols();


            /**************************** Loop until end of file ****************************/
            do
            {
                /******************* Get one line from the file to be parsed **********************/

                ParseIn = newfile.ReadLine();
                ParseIn = ParseIn.Replace("0x", " ");

                /******************* At End of Symbol Block need to move to end state *************/

                if (ParseIn.Contains("[End]"))
                {
                    switch (ParseState)
                    {
                        case PState.MESSAGE_STATE:
                            {
                                ParseState = PState.MESSAGE_END_STATE;
                                break;
                            }
                        case PState.SUBMESSAGE_STATE:
                            {
                                ParseState = PState.SUBMESSAGE_END_STATE;
                                break;
                            }
                        case PState.BITDATA_STATE:
                            {
                                ParseState = PState.BITDATA_END_STATE;
                                break;
                            }
                        case PState.DATAWORD_STATE:
                            {
                                ParseState = PState.DATAWORD_END_STATE;
                                break;
                            }
                        case PState.ENUM_STATE:
                            {
                                ParseState = PState.ENUM_END_STATE;
                                break;
                            }
                        case PState.MESSAGE_DATA_STATE:
                            {
                                ParseState = PState.MESSAGE_DATA_END;
                                break;
                            }
                    }
                }

                /************* main case statement for the parsing state machine ********************/


                switch (ParseState)
                {
                    case PState.START_STATE:
                        {
                            if (ParseIn.Contains("[Message]"))
                            {
                                NewMessage = new Message();
                                ParseState = PState.MESSAGE_STATE;
                            }

                            else if (ParseIn.Contains("[SubMessage]"))
                            {
                                NewSubMessage = new SubMessage();
                                ParseState = PState.SUBMESSAGE_STATE;
                            }
                            else if (ParseIn.Contains("[DataWord]"))
                            {
                                //DataWord NewDataWord = new DataWord();
                                ParseState = PState.DATAWORD_STATE;
                            }
                            else if (ParseIn.Contains("[BitData]"))
                            {
                                //BitData NewBitData = new BitData();
                                ParseState = PState.BITDATA_STATE;
                            }
                            else if (ParseIn.Contains("[EnumIndex]"))
                            {
                                //EnumIndex NewEnumData = new EnumIndex();
                                ParseState = PState.ENUM_STATE;
                            }
                            else if (ParseIn.Contains("[MessageData]"))
                            {
                                ListIn = new ArrayList();
                                ParseState = PState.MESSAGE_DATA_STATE;
                            }

                            break;
                        }



                    case PState.MESSAGE_STATE:
                        {

                            SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);



                            if (SymbolLine.Length != 0)
                            {
                                //richTextBox1.Text = richTextBox1.Text + SymbolLine[1] + '\n';

                                if (SymbolLine[0].Contains("Name"))             /* Message name,.. ex PDOMosi */
                                    NewMessage.Name = SymbolLine[1];
                                else if (SymbolLine[0].Contains("Mask"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.HexNumber);
                                    NewMessage.Mask = NewMask;           /* Message Mask,.. ex 0xFC0 */
                                }
                                else if (SymbolLine[0].Contains("Value"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.HexNumber);
                                    NewMessage.IdentValue = NewMask;            /* Message value,.. ex 0x480 */
                                }
                                else if (SymbolLine[0].Contains("Length"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewMessage.Length = NewMask;                /* Message length,.. ex 4 (bytes) */
                                }
                                else if (SymbolLine[0].Contains("Direction"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewMessage.Direction = NewMask;             /* Message direction,..ex Rx or Tx  */
                                }
                                else if (SymbolLine[0].Contains("SendRate"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewMessage.SendRate = NewMask;                /* Message send rate,.. ex every 4 ms */
                                }
                                else
                                    MessageBox.Show("Data error");
                            }
                            break;
                        }



                    case PState.MESSAGE_END_STATE:
                        {
                            try
                            {
                                MySymbols.NewSymbol.Add(NewMessage.Name, NewMessage);

                            }

                            catch
                            {
                                MessageBox.Show("error in input");
                            }

                            ParseState = PState.START_STATE;


                            break;
                        }




                    case PState.SUBMESSAGE_STATE:
                        {

                            SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);


                            if (SymbolLine.Length != 0)
                            {
                                //richTextBox1.Text = richTextBox1.Text + SymbolLine[1] + '\n';

                                if (SymbolLine[0].Contains("Name"))             /* Message name,.. ex PDOMosi */
                                    NewSubMessage.SubMessageName = SymbolLine[1];
                                else if (SymbolLine[0].Contains("LinkedMessage"))
                                {
                                    //int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.HexNumber);
                                    NewSubMessage.MessageId = SymbolLine[1];                  /* Message Mask,.. ex 0xFC0 */
                                }
                                else if (SymbolLine[0].Contains("Mask"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.HexNumber);
                                    NewSubMessage.Mask = NewMask;                  /* Message Mask,.. ex 0xFC0 */
                                }

                            }
                            break;
                        }

                    case PState.SUBMESSAGE_END_STATE:
                        {
                            try
                            {

                                MySymbols.NewSubId.Add(NewSubMessage.MessageId + NewSubMessage.SubMessageName, NewSubMessage);

                            }

                            catch
                            {
                                MessageBox.Show("error in input");
                            }

                            ParseState = PState.START_STATE;


                            break;
                        }

                    case PState.DATAWORD_STATE:
                        {

                            SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);

                            if (SymbolLine.Length != 0)
                            {

                                if (SymbolLine[0].Contains("Name"))             /* Message name,.. ex PDOMosi */
                                    NewDataWord.Name = SymbolLine[1];
                                else if (SymbolLine[0].Contains("LinkedMessage"))
                                {
                                    NewDataWord.MessageId = SymbolLine[1];      /* Message ID,.. ex PDOMosi */
                                }
                                else if (SymbolLine[0].Contains("LinkedDataEnum"))
                                {
                                    NewDataWord.LinkedData = SymbolLine[1];      /* Message ID,.. ex PDOMosi */
                                }                                
                                else if (SymbolLine[0].Contains("SubIndexStart"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.SubIndexStartByte = NewMask;            /* Message value,.. ex 0x480 */
                                }                                
                                else if (SymbolLine[0].Contains("Start"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.StartByte = NewMask;            /* Message value,.. ex 0x480 */
                                }
                                else if (SymbolLine[0].Contains("WordType"))
                                {
                                    NewDataWord.WordType = SymbolLine[1];      /* Message ID,.. ex PDOMosi */
                                }
                                else if (SymbolLine[0].Contains("Length"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.WordLength = NewMask;           /* Message length,.. ex 4 (bytes) */
                                }
                                else if (SymbolLine[0].Contains("EndianType"))  /* Endian type,.. ex Big or Small */
                                {
                                    NewDataWord.EndianType = SymbolLine[1];
                                }
                                else if (SymbolLine[0].Contains("Format"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.Format = NewMask;                /* Message direction,..ex Rx or Tx  */
                                }
                                else if (SymbolLine[0].Contains("Scaling"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.Scaling = NewMask;                /* Message send rate,.. ex every 4 ms */
                                }
                                else if (SymbolLine[0].Contains("Offset"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewDataWord.ScalingOffset = NewMask;                /* Message send rate,.. ex every 4 ms */
                                }

                                else
                                    MessageBox.Show("Data error");
                            }



                            break;
                        }


                    case PState.DATAWORD_END_STATE:
                        {
                            try
                            {
                                MySymbols.NewData.Add(NewDataWord.Name, NewDataWord);
                            }

                            catch
                            {
                                MessageBox.Show("error in input");
                            }

                            ParseState = PState.START_STATE;

                            break;
                        }




                    case PState.BITDATA_STATE:
                        {
                            SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);

                            if (SymbolLine.Length != 0)
                            {

                                if (SymbolLine[0].Contains("Name"))             /* Message name,.. ex PDOMosi */
                                    NewBitData.Name = SymbolLine[1];
                                else if (SymbolLine[0].Contains("LinkedWord"))
                                {
                                    NewBitData.DataWordName = SymbolLine[1];      /* Message ID,.. ex PDOMosi */
                                }

                                else if (SymbolLine[0].Contains("Length"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewBitData.Length = NewMask;                /* Message length,.. ex 4 (bytes) */
                                }


                                else if (SymbolLine[0].Contains("BitNumber"))
                                {
                                    int NewMask = Int32.Parse(SymbolLine[1], NumberStyles.Integer);
                                    NewBitData.StartbitNumber = NewMask;                /* Message send rate,.. ex every 4 ms */
                                }


                                else if (SymbolLine[0].Contains("LinkedEnumName"))
                                {
                                    NewBitData.EnumLink = SymbolLine[1];      /* LinkedEnumName,.. ex PDOMosi */
                                }

                                else
                                    MessageBox.Show("Data error");
                            }



                            break;
                        }


                    case PState.BITDATA_END_STATE:
                        {
                            try
                            {
                                MySymbols.NewBit.Add(NewBitData.Name, NewBitData);
                            }

                            catch
                            {
                                MessageBox.Show("error in input");
                            }

                            ParseState = PState.START_STATE;



                            break;
                        }





                    case PState.ENUM_STATE:
                        {
                            SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);

                            if (SymbolLine.Length != 0)
                            {

                                if (SymbolLine[0].Contains("Name"))             /* Data Word name,.. ex CommandSpecifier */
                                    NewEnumData.DataWordName = SymbolLine[1];
                                else if (SymbolLine[0].Contains("Index"))
                                {
                                    NewEnumData.Name = SymbolLine[1];       /* Enum Name,.. ex Operational */
                                    string[] Temp = SymbolLine[2].Split(new Char[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);
                                    string Temp1 = String.Join("", Temp);
                                    NewEnumData.Index = Int32.Parse(Temp1, NumberStyles.HexNumber);      /* Enum Value,... ex      */
                                    try
                                    {
                                        MySymbols.NewEnum.Add(NewEnumData.Name, NewEnumData);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("error in input");
                                    }
                                }
                                else
                                    MessageBox.Show("Data error");
                            }

                            break;
                        }

                    case PState.ENUM_END_STATE:
                        {

                            ParseState = PState.START_STATE;


                            break;
                        }


                    case PState.MESSAGE_DATA_STATE:
                        {
                            if (ParseIn != "")
                                ListIn.Add(ParseIn);
                            break;

                        }

                    case PState.MESSAGE_DATA_END:
                        {
                            ParseState = PState.START_STATE;
                            break;
                        }

                }



            } while (newfile.Peek() >= 0);


            FileOpen = false;
            newfile.Close();
            //fs.Close();
        }

          
    

    }


    public class ReadOptionsIni
    {

        private FileStream fs;
        private StreamReader newfile;
        private String ParseIn;
        //CanToolOptionData OptionsOut;
        public String[] SymbolLine;
        char[] TextDelimits = { ' ', ',', '=' };



        public bool GetInitOptions(ref CanToolOptionData OptionsOut, string FilePath)
        {
            
            try
            {
                ReadFile(ref OptionsOut, FilePath);
            }
            catch
            {
                MessageBox.Show("Recreatinging ini file","Ini Error");
                newfile.Close();
                return false;
            }
            return true;

        }
        
        
        public void ReadFile(ref CanToolOptionData OptionsOut, string Path)
        {
            string FileNameIn = Path + @"\Shuaru.ini";
            fs = new FileStream(FileNameIn,
               FileMode.Open, FileAccess.Read);
            newfile = new StreamReader(fs);
            fs.Seek(0, SeekOrigin.Begin);
            newfile.DiscardBufferedData();


/**************************** Loop until end of file ****************************/                                                                                                                   
            do                  
            {                                                          
/******************* Get one line from the file to be parsed **********************/         
                
                ParseIn = newfile.ReadLine();
                SymbolLine = ParseIn.Split(TextDelimits, StringSplitOptions.RemoveEmptyEntries);

                if (ParseIn[0] == ';') // skip comment
                {
                }
                else if (ParseIn.Contains("BaudIndex"))
                {
                     int TempBaud = Int32.Parse(SymbolLine[1]);
                     if ((TempBaud > 0) && (TempBaud < 10))
                         OptionsOut.BaudIndex = TempBaud;
                     else
                         OptionsOut.BaudIndex = 3;
                }
                else if (ParseIn.Contains("hardware"))
                {
                     int TempHardware = Int32.Parse(SymbolLine[1]);
                     if ((TempHardware >= 0) && (TempHardware < 3))
                         OptionsOut.hardware = TempHardware;
                     else
                         OptionsOut.hardware = 2;
                }
                else if (ParseIn.Contains("MainHEXfile"))
                {
                    if (ParseIn.Contains("Browse"))
                        OptionsOut.MainFileName = "Browse for file";
                    else
                        OptionsOut.MainFileName = SymbolLine[1];
                }
                else if (ParseIn.Contains("MainNodeID"))
                {
                    OptionsOut.MainNodeID = SymbolLine[1];
                }
                else if (ParseIn.Contains("port"))
                {
                    OptionsOut.port = SymbolLine[1];
                }
                else if (ParseIn.Contains("serail_number"))
                {
                    OptionsOut.serial_number = SymbolLine[1];
                }
                else if (ParseIn.Contains("security_key"))
                {
                    OptionsOut.security_key = SymbolLine[1];
                }
				
            } while (newfile.Peek() >= 0);
            newfile.Close();


        }



        public void WriteFile(ref CanToolOptionData OptionsOut, string Path)
        {
            
            string FileNameIn = Path + @"\Shuaru.ini";
            FileStream fs = new FileStream(FileNameIn, FileMode.Create);
            StreamWriter newfile = new StreamWriter(fs);
            string DataBuffer = "";

            DataBuffer += "[Flash Tool Options]" + "\r\n";
            DataBuffer += "BaudIndex = " + OptionsOut.BaudIndex.ToString() + "\r\n";
            DataBuffer += "MainHEXfile = " + OptionsOut.MainFileName + "\r\n";
            DataBuffer += "MainNodeID = " + OptionsOut.MainNodeID + "\r\n";
			DataBuffer += "hardware = " + OptionsOut.hardware + "\r\n";
			DataBuffer += ";0 - vector hardware\r\n";
			DataBuffer += ";1 - peak can hardware\r\n";
			DataBuffer += ";2 - Linde can\r\n";
            DataBuffer += "port = " + OptionsOut.port + "\r\n";
			DataBuffer += ";Linde can port\r\n";
			DataBuffer += "serail_number = " + OptionsOut.serial_number+ "\r\n";
			DataBuffer += ";ES22 controller serial number\r\n";
			DataBuffer += "security_key = " + OptionsOut.security_key+ "\r\n";
            DataBuffer += ";security key";
            newfile.WriteLine(DataBuffer);
            newfile.Close();
            fs.Close();
        }



    }


}
